#autodesk 3ds parser
#http://the-labs.com/Blender/3DS-details.html

import os, sys
from Sanae3D.lib.ModelObject import Model3D
from Sanae3D.lib.StructReader import StructReader

class Autodesk_3DS(Model3D):
    '''Replace 'Autodesk_3DS' with a suitable name of your choice. Try to follow
    the standard: GameName_FormatExt'''
    
    def __init__(self, obj3D=None, outFile=None, inFile=None):
        
        super(Autodesk_3DS,self).__init__("XAC")
        self.obj3D = obj3D
        self.inFile = inFile
        self.outFile = outFile
        self.materials = []
        
    def read_name(self):
        
        name = []
        char = self.inFile.read_char()
        while char != "\x00":
            name.append(char)
            char = self.inFile.read_char()
        return ''.join(name)
    
    def parse_materials(self, length):
        
        sectEnd = self.inFile.tell() + length
        
        while self.inFile.tell() != sectEnd:
            chunk = self.inFile.read_ushort()
            chunkLen = self.inFile.read_long() - 6
            
            if chunk == 0xA000:
                matNum = self.mat_count()
                matName =  self.read_name()
                self.materials.append(matName)
                self.create_material(matNum)
                self.add_material_name(matNum, matName)
            elif chunk in set([0xA010, 0xA020, 0xA030, 0xA040]):
                pass
            elif chunk == 0x0011:
                #color_24
                rgb = self.inFile.read_ubyte(3)
            elif chunk == 0x0030:
                #percentage
                self.inFile.read_short()
            elif chunk == 0xA200:
                print chunkLen
            else:
                self.inFile.seek(chunkLen, 1)
    
    def parse_vertices(self, meshName):
        
        numVerts = self.inFile.read_ushort()
        verts = self.inFile.read_float(numVerts*3)
        for i in xrange(0, numVerts*3, 3):
            coords = verts[i:i+3]
            
            self.create_vertex(meshName, i / 3)
            self.add_coords(meshName, i / 3, coords)
            
    def parse_faces(self, meshName):
    
        numFaces = self.inFile.read_ushort()
        print "%d faces" %numFaces
        
        faces = self.inFile.read_ushort(4*numFaces)
        for i in xrange(0, numFaces*4, 4):
            verts = faces[i:i+3]
            flag = faces[i+3]
            
            self.create_face(meshName, i / 4)
            self.add_face_verts(meshName, i / 4, verts)            
            
    def parse_face_material(self, meshName):
        
        matName = self.read_name()
        matNum = self.materials.index(matName)
        
        numFaces = self.inFile.read_short()
        faces = self.inFile.read_short(numFaces)
        for i in xrange(numFaces):
            self.add_face_material(meshName, i, matNum)
        
    def parse_mesh(self, length):
        
        sectEnd = self.inFile.tell() + length
        meshName = self.read_name()
        self.create_object(meshName)
        #print meshName
        
        while self.inFile.tell() != sectEnd:
            chunk = self.inFile.read_ushort()
            chunkLen = self.inFile.read_long() - 6
            if chunk == 0x4100:
                pass
            elif chunk == 0x4110:
                self.parse_vertices(meshName)
            elif chunk == 0x4120:
                self.parse_faces(meshName)
            elif chunk == 0x4130:
                self.parse_face_material(meshName)
            elif chunk == 0x4160:
                #matrix
                self.inFile.read_float(12)
            else:
                self.inFile.seek(chunkLen, 1)
        
    def parse_file(self):
        '''Main parser method. Can be replaced'''
        
        filesize = self.inFile.filesize()
        
        while self.inFile.tell() != filesize:
            chunk = self.inFile.read_ushort()
            chunkLen = self.inFile.read_long() - 6
            
            #print hex(chunk), self.inFile.tell(), chunkLen
            if chunk == 0x4D4D:
                pass
            elif chunk == 0x3D3D:
                #mesh start
                pass
            elif chunk == 0x4000:
                self.parse_mesh(chunkLen)
            elif chunk == 0x0002:
                version = self.inFile.read_long()
            elif chunk == 0xAFFF:
                self.parse_materials(chunkLen)
            else:
                self.inFile.seek(chunkLen, 1)
        
def read_file(path):
    '''Read the file'''
    
    openFile = StructReader(open(path, 'rb'))
    obj = Autodesk_3DS(inFile=openFile)
    obj.parse_file()
    openFile.close()
    return obj

def write_file(path):
    
    pass

def definitions():
    '''Return the header, extension, and a description of the format'''
    
    return "\x4D\x4D", "3DS", "Autodesk 3DS"

if __name__ == '__main__':
    
    file1 = "Wheel.3DS"
    obj = read_file(file1)